using System;
using System.Collections.Generic;

public partial class FloodFill
{
    public static List<T> Fill<T>(T start, T[,] map, RobotMoveType type) where T : MoveGrid
    {
        // 已经确定的节点
        var closeList = new List<T>();
        // 待确定的节点
        var openList = new Queue<T>();
        // 哪个机体要计算移动范围
        var originRobot = start.RobotOnGrid;

        // 将起始节点加入待确定的节点列表
        openList.Enqueue(start);

        // 循环
        while (openList.Count > 0)
        {
            // 取出待确定的节点列表中的第一个节点
            var node = openList.Dequeue();
            // 将该节点加入已经确定的节点列表
            if (!closeList.Contains(node)) closeList.Add(node);
            // 获取该节点的周围节点
            var neighbors = GetNeighbors(originRobot, node, map);
            // 遍历周围节点
            foreach (var neighbor in neighbors)
            {
                // 如果已经访问过，跳过
                if (closeList.Contains(neighbor)) continue;
                // 计算剩余移动点
                int remain = node.Remain - neighbor.MoveCost[type.ToString()].As<int>();
                // 如果新计算的剩余移动点大于于当前节点的剩余移动点，更新当前节点的剩余移动点
                if (neighbor.Remain < remain && remain >= 0)
                {
                    neighbor.Remain = remain;
                    neighbor.Previous = node;
                    openList.Enqueue(neighbor);
                }
            }
        }
        return closeList;
    }

    static void ValidateGridCanMove<T>(int x, int y, Robot originRobot, List<T> list, T[,] map) where T : MoveGrid
    {
        if (map[x, y] == null) return;
        // 格子上没有机体，一定可以移动
        if (map[x, y]?.RobotOnGrid == null)
        {
            list.Add(map[x, y]);
        }
        else
        {
            // 格子上有机体
            var robot = map[x, y].RobotOnGrid;
            // 空中类型的机体 ， 无视 陆型和海型的机体
            if (originRobot.Entity.MoveType == RobotMoveType.AIR && robot.Entity.MoveType != RobotMoveType.AIR)
            {
                list.Add(map[x, y]);
            }
            // 陆型和海型的机体 ， 无视 空中类型的机体
            if (originRobot.Entity.MoveType != RobotMoveType.AIR && robot.Entity.MoveType == RobotMoveType.AIR)
            {
                list.Add(map[x, y]);
            }
            // 若是母舰机体，并且是盟友 ，则也在移动范围内
            if (robot.Entity.IsMotherShip)
            {
                if (robot.AllyToOther(originRobot))
                {
                    list.Add(map[x, y]);
                }
            }
        }
    }

    private static List<T> GetNeighbors<T>(Robot robot, T node, T[,] map) where T : MoveGrid
    {
        var maxX = map.GetLength(0);
        var maxY = map.GetLength(1);
        var list = new List<T>();
        // 找上方的节点
        var x = node.MapX;
        var y = node.MapY - 1;
        if (y >= 0 && y < maxY)
        {
            ValidateGridCanMove(x, y, robot, list, map);
        }
        // 找下方的节点
        x = node.MapX;
        y = node.MapY + 1;
        if (y >= 0 && y < maxY)
        {
            ValidateGridCanMove(x, y, robot, list, map);
        }
        // 找左方的节点
        x = node.MapX - 1;
        y = node.MapY;
        if (x >= 0 && x < maxX)
        {
            ValidateGridCanMove(x, y, robot, list, map);
        }
        // 找右方的节点
        x = node.MapX + 1;
        y = node.MapY;
        if (x >= 0 && x < maxX)
        {
            ValidateGridCanMove(x, y, robot, list, map);
        }

        return list;
    }
}